/*************************************************************************
 *
 *   file		: Statistics.cs
 *   copyright		: (C) The WCell Team
 *   email		: info@wcell.org
 *   last changed	: $LastChangedDate: 2008-06-07 17:55:09 +0100 (Sat, 07 Jun 2008) $
 *   last author	: $LastChangedBy: dominikseifert $
 *   revision		: $Rev: 458 $
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WCell.Core.Initialization;
using WCell.Core;
using WCell.Constants;
using WCell.Core.Timers;
using WCell.Cryptography;
using Cell.Core;
using WCell.Core.Network;
using NLog;
using Cell.Core.Collections;
using System.Threading;

namespace WCell.RealmServer.Statistics
{
	public static class Statistics
	{
		private static readonly Logger log = LogManager.GetCurrentClassLogger();

		/// <summary>
		/// Wether to start the Statistics timer on startup.
		/// Toggled off if developing (since it delays startup by 2 extra seconds)
		/// </summary>
#if DEV
		public static bool LoadOnStartup = false;
#else
		public static bool LoadOnStartup = true;
#endif

		private static Timer m_bandwidthStatsConsumer;
		private static StatisticsTimer s_timer;
		private static Dictionary<uint, BigInteger> m_bandwidthStats;
		private static SynchronizedQueue<BandwidthStatistic> m_queuedBandwidthStats;

		[Initialization(InitializationPass.Fifth, Name = "Start statistics timer")]
		public static void StartStatistics()
		{
			if (LoadOnStartup)
			{
				m_queuedBandwidthStats = new SynchronizedQueue<BandwidthStatistic>();
				m_bandwidthStats = new Dictionary<uint, BigInteger>();

				foreach (RealmServerOpCode opcode in (RealmServerOpCode[])Enum.GetValues(typeof(RealmServerOpCode)))
				{
					if (!m_bandwidthStats.ContainsKey((uint)opcode))
					{
						m_bandwidthStats.Add((uint)opcode, new BigInteger(0));
					}
				}

				m_bandwidthStatsConsumer = new Timer((state) => UpdateBandwidthUsage());
				m_bandwidthStatsConsumer.Change(5000, 5000);

				s_timer = new StatisticsTimer(RealmServer.Instance.Configuration.StatsInterval * 1000);
				s_timer.Start();
			}
		}

		public static void StoreBandwidth(BandwidthStatistic stat)
		{
			m_queuedBandwidthStats.Enqueue(stat);
		}

		private static void UpdateBandwidthUsage()
		{
			BandwidthStatistic[] stats = m_queuedBandwidthStats.ToArray();

			foreach (BandwidthStatistic stat in stats)
			{
				m_bandwidthStats[((PacketId)stat.OpCode).RawId] += stat.PacketSize;
			}
		}

		public static string FormatBytes(float num)
		{
			string numPrefix = "B";

			if (num >= 1024f)
			{
				num /= 1024.0f; numPrefix = "kB";
			}
			if (num >= 1024f)
			{
				num /= 1024.0f; numPrefix = "MB";
			}
			if (num >= 1024f)
			{
				num /= 1024.0f; numPrefix = "GB";
			}

			return string.Format("{0,6:f}{1}", num, numPrefix);
		}

		public static string FormatBytes(double num)
		{
			string numPrefix = "B";

			if (num >= 1024.0)
			{
				num /= 1024.0; numPrefix = "kB";
			}
			if (num >= 1024.0)
			{
				num /= 1024.0; numPrefix = "MB";
			}
			if (num >= 1024.0)
			{
				num /= 1024.0; numPrefix = "GB";
			}

			return string.Format("{0,6:f}{1}", num, numPrefix);
		}
	}
}
